package com.qingzhou.framework.interceptor;

import cn.hutool.core.util.StrUtil;
import com.qingzhou.common.utils.XssUtil;
import com.qingzhou.common.web.api.ApiCode;
import com.qingzhou.common.web.api.ApiCodes;
import org.noear.solon.annotation.Component;
import org.noear.solon.core.handle.Context;
import org.noear.solon.core.handle.Handler;
import org.noear.solon.core.handle.Result;
import org.noear.solon.core.route.RouterInterceptor;
import org.noear.solon.core.route.RouterInterceptorChain;

import java.util.Map;

/**
 * 全局路由拦截器
 * @author xm
 */
@Component
public class GlobalRouterInterceptor implements RouterInterceptor {

    // 以下前缀的路径不统一返回结果（监控、接口文档）
    private static final String[] ignorePaths = { "/solon-admin", "/swagger" };

    @Override
    public void doIntercept(Context ctx, Handler mainHandler, RouterInterceptorChain chain) throws Throwable {
        // XSS
        if (mainHandler != null) {
            // 请求头
            for (Map.Entry<String, String> kv : ctx.headerMap().entrySet()) {
                // 处理Val
                kv.setValue(cleanXss(kv.getValue()));
            }
            // 请求参数
            for (Map.Entry<String, String> kv : ctx.paramMap().entrySet()) {
                // 处理val
                kv.setValue(cleanXss(kv.getValue()));
            }
            // 请求主体
            if (ctx.contentType() != null && ctx.contentType().contains("json")) {
                // 处理vaL
                ctx.bodyNew(cleanXss(ctx.body()));
            }
        }
        chain.doIntercept(ctx, mainHandler);
    }

    /**
     * 统一的返回结果（将所有返回结果统一为Result，render执行前调用）
     */
    @Override
    public Object postResult(Context ctx, Object obj) throws Throwable {
        // 部分路径不统一返回结果
        if(StrUtil.startWithAny(ctx.pathAsLower(), ignorePaths)) {
            return obj;
        }
        // 如果没有按Result tyle 渲染
        if (obj == null && ctx.status() == 404) {
            obj = ApiCodes.CODE_404;
        }
        Result result = null;
        if (obj instanceof ApiCode) {
            // 处理标准的状态码
            ApiCode apiCode = (ApiCode) obj;
            result = Result.failure(apiCode.getCode(), apiCode.getDescription());
        } else if (obj instanceof Throwable) {
            // 处理异常
            Throwable throwable = (Throwable) obj;
            throwable.printStackTrace();  // 打印异常
            ApiCode apiCode = ApiCodes.CODE_400(throwable);
            result = Result.failure(apiCode.getCode(), apiCode.getDescription());
        } else if (obj instanceof Result) {
            // 处理Result结构
            result = (Result) obj;
        } else {
            // 处理java bean数据（为扩展新的）
            result = Result.succeed(obj);
        }
        return result;
    }

    private String cleanXss(String input) {
        if (StrUtil.isBlankOrUndefined(input)) {
            return input;
        }
        input = XssUtil.removeEvent(input);
        input = XssUtil.removeScript(input);
        input = XssUtil.removeEval(input);
        input = XssUtil.swapJavascript(input);
        input = XssUtil.swapVbscript(input);
        input = XssUtil.swapLivescript(input);
        input = XssUtil.encode(input);
        return input;
    }

}
